package com.ynet.middleground.riskmanage.utils;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

import org.json.XML;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ynet.cache.redis.IfpRedisson;
import com.ynet.core.common.BaseReqObj;
import com.ynet.core.log.IfpLogger;
import com.ynet.host.client.HostSenderService;
import com.ynet.host.http.HttpRequest;
import com.ynet.host.http.HttpResponse;
import com.ynet.middleground.riskmanage.dao.ServiceLogMapper;
import com.ynet.middleground.riskmanage.entity.ServiceLog;
import com.ynet.middleground.riskmanage.filter.SpecialLogFilter;

/**
 * @author liulx
 * @description api 请求工具类
 * @date 2020-08-07 12:26
 */
@Component
public class ApiUtil {

    @Autowired
    private HostSenderService hostSenderService;

    @Autowired
    private ServiceLogMapper serviceLogMapper;

    @Autowired
    private IfpRedisson redisson;

    /**
     * redis 全局日志记录开关
     */
    public static String REDIS_KEY = "ifp:system:settings:logswitch";

    /**
     * 向 api 服务发送请求
     *
     * @param headMap 请求头参数
     * @param params 请求信息参数
     * @param url 请求完整地址
     * @param httpMethod 请求方式
     * @param desc 服务提供商名称
     * @return api 服务响应对象
     */
    public JSONObject sendApi(Map<String, String> headMap, Map<String, Object> params, String url, String httpMethod,
        String desc) {
        HttpRequest request = new HttpRequest();
        request.setUrl(url);
        request.setMethod(httpMethod);
        request.setMessage(params);
        if ("GET".equalsIgnoreCase(httpMethod)) {
            Map<String, String> getParams = new HashMap<>(16);
            params.forEach((k, v) -> {
                getParams.put(k, String.valueOf(v));
            });
            request.setParams(getParams);
        }
        request.setHeader(headMap);
        JSONObject apiResult;
        Object json = JSONObject.toJSON(request);

        // IfpLogger.info(Thread.currentThread().getStackTrace()[1].getMethodName(),
        // " 开始 " + LocalDate.now() + "请求地址" + url);
        // IfpLogger.info(Thread.currentThread().getStackTrace()[1].getMethodName(),
        // " 开始 " + LocalDate.now() + "请求" + desc + "\n参数：" + json, request);

        IfpLogger.info(
            SpecialLogFilter.FILTER_FOR_LOGSTASH_PREFIX + Thread.currentThread().getStackTrace()[1].getMethodName(),
            " 开始 " + LocalDate.now() + "请求地址" + url);
        IfpLogger.info(
            SpecialLogFilter.FILTER_FOR_LOGSTASH_PREFIX + Thread.currentThread().getStackTrace()[1].getMethodName(),
            " 开始 " + LocalDate.now() + "请求" + desc + "\n参数：" + json, request);

        HttpResponse response = (HttpResponse)hostSenderService.request("id_http", request, JSONObject.class);
        Object responseJson = JSONObject.toJSON(response);

        // IfpLogger.info(Thread.currentThread().getStackTrace()[1].getMethodName(),
        // " 结束 " + LocalDate.now() + desc + "响应\n报文：" + responseJson, response);
        // // 这是响应的头信息
        // // 这是响应的 http 状态码，只有合法的状态才会返回，其它状态码会抛异常
        // // 200 为默认的合法状态码，如有需求，可在 yml 中可自定义其它状态码
        // IfpLogger.info(Thread.currentThread().getStackTrace()[1].getMethodName(),
        // " 请求" + desc + " api 服务, api 地址: {}， 响应状态码，status: {}", url, response.getStatus());

        IfpLogger.info(
            SpecialLogFilter.FILTER_FOR_LOGSTASH_PREFIX + Thread.currentThread().getStackTrace()[1].getMethodName(),
            " 结束 " + LocalDate.now() + desc + "响应\n报文：" + responseJson, response);
        IfpLogger.info(
            SpecialLogFilter.FILTER_FOR_LOGSTASH_PREFIX + Thread.currentThread().getStackTrace()[1].getMethodName(),
            " 请求" + desc + " api 服务, api 地址: {}， 响应状态码，status: {}", url, response.getStatus());

        // 这是响应的报文体反格式化之后的对象
        apiResult = (JSONObject)response.getMessage();
        return apiResult;
    }

    /**
     * 向 api 服务发送请求并记录日志
     * 
     * @param interfaceCode 请求 api 接口的编码
     * @param url 请求完整地址
     * @param head 请求头参数
     * @param params 请求信息参数
     * @param httpMethod 请求方式
     * @param providerName 服务提供商名称
     * @param reqObj 基础请求对象
     * @return api 服务响应对象
     */
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    public JSONObject sendApiLog(String interfaceCode, String url, Map<String, String> head, Map<String, Object> params,
        String httpMethod, String providerName, BaseReqObj reqObj) {
        // 方法开始执行的时间
        long startTime = System.currentTimeMillis();
        JSONObject apiResult = sendApi(head, params, url, httpMethod, providerName);
        // 记录方法正常执行后时间
        long methodEnd = System.currentTimeMillis();
        String o = redisson.get(REDIS_KEY);
        if (o == null || "1".equals(o)) {
            ServiceLog log = new ServiceLog();
            log.setServiceCode(interfaceCode);
            log.setRequestMsg(JSON.toJSONString(params));
            log.setResponseMsg(apiResult == null ? null : apiResult.toJSONString());
            log.setResDate(LocalDateTime.now());
            log.setChannel(reqObj.getChannel());
            log.setCostTime(Math.toIntExact((methodEnd - startTime)));
            log.setGmtCreate(LocalDateTime.now());
            log.setCreateBy(reqObj.getOperationUserId());
            log.setGmtModified(LocalDateTime.now());
            log.setModifiedBy(reqObj.getOperationUserId());
            serviceLogMapper.insert(log);
        }
        return apiResult;
    }

    /**
     * 向 api 服务发送请求
     *
     * @param headMap 请求头参数
     * @param params 请求信息参数
     * @param url 请求完整地址
     * @param httpMethod 请求方式
     * @param desc 服务提供商名称
     * @return api 服务响应对象
     */
    public String sendXMLApi(Map<String, String> headMap, String params, String url, String httpMethod, String desc) {
        HttpRequest request = new HttpRequest();
        request.setUrl(url);
        request.setMethod(httpMethod);
        request.setMessage(params);
        // if ("GET".equalsIgnoreCase(httpMethod)) {
        // Map<String, String> getParams = new HashMap<>(16);
        // params.forEach((k, v) -> {
        // getParams.put(k, String.valueOf(v));
        // });
        // request.setParams(getParams);
        // }
        request.setHeader(headMap);
        JSONObject apiResult;
        Object json = JSONObject.toJSON(request);
        IfpLogger.info(Thread.currentThread().getStackTrace()[1].getMethodName(),
            " 开始 " + LocalDate.now() + "请求地址" + url);
        IfpLogger.info(Thread.currentThread().getStackTrace()[1].getMethodName(),
            " 开始 " + LocalDate.now() + "请求" + desc + "\n参数：" + json, request);
        HttpResponse response = (HttpResponse)hostSenderService.request("id_http_xml", request, XML.class);

        Object responseJson = JSONObject.toJSON(response);
        IfpLogger.info(Thread.currentThread().getStackTrace()[1].getMethodName(),
            " 结束 " + LocalDate.now() + desc + "响应\n报文：" + responseJson, response);
        // 这是响应的头信息
        // 这是响应的 http 状态码，只有合法的状态才会返回，其它状态码会抛异常
        // 200 为默认的合法状态码，如有需求，可在 yml 中可自定义其它状态码
        IfpLogger.info(Thread.currentThread().getStackTrace()[1].getMethodName(),
            " 请求" + desc + " api 服务, api 地址: {}， 响应状态码，status: {}", url, response.getStatus());
        // 这是响应的报文体反格式化之后的对象
        // apiResult = (JSONObject)response.getMessage();
        return response.getMessage().toString();
    }

    /**
     * 向 api 服务发送请求并记录日志
     *
     * @param interfaceCode 请求 api 接口的编码
     * @param url 请求完整地址
     * @param head 请求头参数
     * @param params 请求信息参数
     * @param httpMethod 请求方式
     * @param providerName 服务提供商名称
     * @param reqObj 基础请求对象
     * @return api 服务响应对象
     */
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    public String sendXMLApiLog(String interfaceCode, String url, Map<String, String> head, String params,
        String httpMethod, String providerName, BaseReqObj reqObj) {
        // 方法开始执行的时间
        long startTime = System.currentTimeMillis();
        String apiResult = sendXMLApi(head, params, url, httpMethod, providerName);
        // 记录方法正常执行后时间
        long methodEnd = System.currentTimeMillis();
        String o = redisson.get(REDIS_KEY);
        if (o == null || "1".equals(o)) {
            ServiceLog log = new ServiceLog();
            log.setServiceCode(interfaceCode);
            log.setRequestMsg(JSON.toJSONString(params));
            log.setResponseMsg(apiResult);
            log.setResDate(LocalDateTime.now());
            log.setChannel(reqObj.getChannel());
            log.setCostTime(Math.toIntExact((methodEnd - startTime)));
            log.setGmtCreate(LocalDateTime.now());
            log.setCreateBy(reqObj.getOperationUserId());
            log.setGmtModified(LocalDateTime.now());
            log.setModifiedBy(reqObj.getOperationUserId());
            serviceLogMapper.insert(log);
        }
        return apiResult;
    }
}
